package com.allen.admin.config.shiro;

import org.apache.shiro.mgt.CachingSecurityManager;
import org.apache.shiro.spring.LifecycleBeanPostProcessor;
import org.apache.shiro.spring.security.interceptor.AuthorizationAttributeSourceAdvisor;
import org.apache.shiro.spring.web.ShiroFilterFactoryBean;
import org.apache.shiro.web.mgt.DefaultWebSecurityManager;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.aop.framework.autoproxy.DefaultAdvisorAutoProxyCreator;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Qualifier;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.context.annotation.DependsOn;
import org.springframework.core.env.Environment;
import org.springframework.data.redis.cache.DefaultRedisCachePrefix;
import org.springframework.data.redis.cache.RedisCacheManager;
import org.springframework.data.redis.cache.RedisCachePrefix;
import org.springframework.data.redis.core.RedisTemplate;

import javax.servlet.Filter;
import java.util.HashMap;
import java.util.LinkedHashMap;
import java.util.Map;

/**
 * 
 *
 *
 */

public class ShiroConfig {
	
	private static final Logger logger = LoggerFactory.getLogger(ShiroConfig.class);
	
	@Autowired
	private Environment env;
	
	@Autowired
	@Qualifier("shiroRedisTemplate")
	private RedisTemplate<?, ?> redisTemplate;

//    @Bean
//    public ShiroRealm shiroRealm() {
//    	return new ShiroRealm();
//    }
    
    @Bean
    public AjaxUserFilter ajaxUserFilter() {
    	return new AjaxUserFilter();
    }
    
    /**
     * shiro核心安全管理类
     * @return
     */
    @Bean
    public CachingSecurityManager securityManager() {
    	logger.info("Shiro redis cache manager init");
    	
    	RedisCachePrefix cachePrefix = new DefaultRedisCachePrefix();
    	cachePrefix.prefix("hs:admin:shiro");
    	
    	RedisCacheManager redisCacheManager = new RedisCacheManager(redisTemplate);
    	redisCacheManager.setUsePrefix(true);
    	redisCacheManager.setCachePrefix(cachePrefix);
    	// 30min
    	redisCacheManager.setDefaultExpiration(60 * 30);
    	
        ShiroCacheManager cacheManager = new ShiroCacheManager();
        cacheManager.setCacheManger(redisCacheManager);
    	
    	logger.info("Shiro security manager init");
        CachingSecurityManager securityManager = new DefaultWebSecurityManager();
        securityManager.setCacheManager(cacheManager);
        return securityManager;
    }

	@Bean
	public ShiroFilterFactoryBean shiroFilter() {
		logger.info("Shiro filter factory bean manager init");

		ShiroFilterFactoryBean shiroFilter = new ShiroFilterFactoryBean();
		// 必须设置 SecurityManager
		shiroFilter.setSecurityManager(securityManager());
		
		// 如果不设置默认会自动寻找Web工程根目录下的"/login.jsp"页面
		shiroFilter.setLoginUrl(env.getProperty("hs.admin.support.path.login", "https://admin.hstong.com/login"));
		// 登录成功后要跳转的链接
		shiroFilter.setSuccessUrl("/");
		// 未授权界面;
		// factoryBean.setUnauthorizedUrl("/403");

		// 拦截器
		Map<String, String> filterChainDefinitionMap = new LinkedHashMap<>();
		// 静态资源允许访问
		filterChainDefinitionMap.put("/resources/**", "anon");
		// 登录页允许访问
		filterChainDefinitionMap.put("/captcha.jpg", "anon");
		filterChainDefinitionMap.put("/login", "anon");
		filterChainDefinitionMap.put("/third-login/**", "anon");
		
		filterChainDefinitionMap.put("/hsapi/**", "anon");
		// 其他资源需要认证
		filterChainDefinitionMap.put("/**", "user, authc");
		shiroFilter.setFilterChainDefinitionMap(filterChainDefinitionMap);

		Map<String, Filter> filters = new HashMap<String, Filter>(1);
		filters.put("user", ajaxUserFilter());
		shiroFilter.setFilters(filters);

		return shiroFilter;
	}
	
	@Bean
	public static LifecycleBeanPostProcessor lifecycleBeanPostProcessor() {
		return new LifecycleBeanPostProcessor();
	}
	
	@Bean
	@DependsOn("lifecycleBeanPostProcessor")
	public DefaultAdvisorAutoProxyCreator defaultAdvisorAutoProxyCreator() {
		DefaultAdvisorAutoProxyCreator creator = new DefaultAdvisorAutoProxyCreator();
		creator.setProxyTargetClass(true);
		return creator;
	}

    /**
     * 开启 SHIRO AOP 注解支持<br>
     * 使用代理方式 所以需要开启代码支持<br/>
     * 拦截 @RequiresPermissions 注释的方法
     * @return
     */
    @Bean
    @DependsOn("lifecycleBeanPostProcessor")
    public AuthorizationAttributeSourceAdvisor authorizationAttributeSourceAdvisor() {
    	logger.info("Shiro authorizaion attribute source advisor init");
        AuthorizationAttributeSourceAdvisor advisor = new AuthorizationAttributeSourceAdvisor();
        advisor.setSecurityManager(securityManager());
        return advisor;
    }
	
}
